package com.example.sandbox.handler;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Arrays;
import java.util.List;

/**
 * @author: liuxinxin
 * @date: 2024/04/19
 **/

@RestControllerAdvice
@Slf4j
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> {

    private static final String SWAGGER_CLASS_PREFIX = "springfox.documentation";

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return filter(methodParameter);
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType,
        Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest,
        ServerHttpResponse serverHttpResponse) {
        ApiResponse<Object> apiResponse = ApiResponse.of(o);
        // 处理字符串时，遇到了类型转换的问题，debug一步一步跟踪，原来是对于字符串的ContentType是“text-plain”，
        // ConverterType是StringHttpMessageConverter这个类型转换，
        // 由于将结果封装成了自定义的ApiResponse类型，所以有ApiResponse转换成String报错
        // 所以需要对String类型的返回值单独进行处理
        if (o instanceof String) {
            return JSONObject.toJSONString(apiResponse);
        }
        return ApiResponse.of(o);
    }

    private Boolean filter(MethodParameter methodParameter) {
        Class<?> declaringClass = methodParameter.getDeclaringClass();
        // swagger中的所有返回不进行统一封装
        if (declaringClass.getName().contains(SWAGGER_CLASS_PREFIX)) {
            return false;
        }
        if (methodParameter.hasMethodAnnotation(ExceptionHandler.class)) {
            return false;
        }

        if (methodParameter.getParameterType().equals(SingleResponse.class)) {
            return false;
        }
        if (isNeedFilter(declaringClass.getName())) {
            // 如果本身就是使用ApiResponse返回，则不需要进行格式化
            return !methodParameter.getParameterType().equals(ApiResponse.class);
        }

        return false;
    }

    /**
     * 判断是否在为需要包装返回体Response的controller
     *
     * @param declaringClassName
     * @return
     */
    private Boolean isNeedFilter(String declaringClassName) {
        List<String> responseFilterPathList = Arrays.asList("com.funstone", ".controller");
        if (CollectionUtil.isNotEmpty(responseFilterPathList)) {
            for (String path : responseFilterPathList) {
                if (!declaringClassName.contains(path)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
}
